package com.yeung.tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * 事务的传播行为:
 * 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播,方法可能继续在现有事务中运行
 * 也可以开启一个新的事务,并在自己的事务中运行.
 * 有7类传播行为:
 * REQUIRED(0),  有事务在运行,则在其事务内运行(事务的默认行为)
 * SUPPORTS(1),
 * MANDATORY(2),
 * REQUIRES_NEW(3),  使用自己的事务,有事务在运行会将其挂起
 * NOT_SUPPORTED(4),
 * NEVER(5),
 * NESTED(6);
 */
@Service
public class BookShopServiceImp implements BookShopService {
    @Autowired
    private BookShopDao bookShopDao;

    /**
     * 配置事务注解
     * isolation = Isolation.READ_COMMITTED 指事务的隔离级别,最常用的取值
     * 默认情况下 spring的生命十五对所有的运行时异常进行回滚,也可以通过对应的属性进心设置
     * noRollbackFor=UserAccountException.class 指定对于哪些异常不进行回滚操作
     * readOnly = false  指定事务是否只读,表示事务只读取数据但不更新数据,帮助优化数据库引擎
     * timeout指定强制回滚之前事务可以占用的时间
     */

    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.READ_COMMITTED,
            readOnly = false,
            timeout = 1
    )
    @Override
    public void purchase(String userName, int isbn) {
        //配置了事务之后,方法内的业务必须同时成功才可以
        int bookPrice = bookShopDao.findBookPriceByIsbn(isbn);
        int price = 300;
        //更新余额
        try {
            bookShopDao.updateUserAccount(userName, price);
            //减库存
            bookShopDao.updateBookStock(isbn);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Transactional
    @Override
    public void checkOut(String userName, int[] isbns) {
        for (int isbn : isbns) {
            purchase(userName, isbn);
        }
    }

}
